package flush

import (
	"fmt"
	logger "gitee.com/zaper/private-logger"
	"gitee.com/zaper/service-config-client/constant"
	"io"
	"os"
	"path"
	"runtime/debug"
)

type CommConfigFlush struct {
	configFlush *FlushModel
}

func NewCommConfigFlush(cfgFlush *FlushModel) *CommConfigFlush {
	return &CommConfigFlush{
		configFlush: cfgFlush,
	}
}

func (commConfigFlush *CommConfigFlush) Flush(configValue string) bool {
	commConfigFlush.configFlush.sw.Lock()
	defer commConfigFlush.configFlush.sw.Unlock()
	var file *os.File
	defer func() {
		e := recover()
		if e != nil {
			logger.Errorf("Flush fail fail, stack is %s", debug.Stack())
		}
	}()
	defer func() {
		if file != nil {
			err := file.Close()
			if err != nil {
				logger.Errorf("Close file error %s", err)
				return
			}
		}
	}()
	if ok := commConfigFlush.writeConfigPre(); !ok {
		logger.Errorf("writeConfigPre fail, effice config, return")
		return false
	}
	fileStr := path.Join(commConfigFlush.configFlush.FilePath, commConfigFlush.configFlush.FileName)
	file, err := os.OpenFile(fileStr, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755)
	if err != nil {
		logger.Errorf("OpenFile file filePath is %s,err is %s", fileStr, err)
		return false
	}
	_, err = file.Write([]byte(configValue))
	if err != nil {
		logger.Errorf("Write data fail, err is %s", err)
		return false
	}
	logger.Printf("flush success %s", configValue)
	return true
}

// writeConfigPre 用于创建配置目录，创建配置文件，以及备份配置文件操作
func (commConfigFlush *CommConfigFlush) writeConfigPre() bool {
	var file *os.File
	var backFile *os.File
	defer func() {
		if file != nil {
			file.Close()
		}
		if backFile != nil {
			backFile.Close()
		}
	}()
	// 初始化配置目录
	_, err := os.Stat(commConfigFlush.configFlush.FilePath)
	if os.IsNotExist(err) {
		err = os.MkdirAll(commConfigFlush.configFlush.FilePath, 0755)
		if err != nil {
			logger.Errorf("create path fail, err is %s", err)
			return false
		}
	}

	// 初始化备份文件
	fileStr := path.Join(commConfigFlush.configFlush.FilePath, commConfigFlush.configFlush.FileName)
	_, err = os.Stat(fileStr)
	if os.IsNotExist(err) {
		// 首次初始化配置文件
		file, err = os.Create(fileStr)
		if err != nil {
			logger.Errorf("create file fail, err is %s", err)
			return false
		}
	} else {
		// 后续备份配置文件
		file, err = os.OpenFile(fileStr, os.O_RDWR, 0755)
		backFileStr := fmt.Sprintf("%s%s", commConfigFlush.configFlush.FileName, "_back")
		backPath := path.Join(commConfigFlush.configFlush.FilePath, backFileStr)
		backFile, err = os.OpenFile(backPath, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0755)
		if err != nil {
			logger.Errorf("OpenFile backfile filePath is %s,err is %s", fileStr, err)
			return false
		}
		_, e := io.Copy(backFile, file)
		if e != nil {
			logger.Errorf("back config fail,err %v", e)
			return false
		}
	}
	return true
}

func GetMessFlush(configName string) ConfigFlusher {
	flushManager := GetFlushManager()
	var flushConfigModel *FlushModel
	switch configName {
	case constant.GaussDB:
		flushConfigModel = flushManager.GetDBFlushConfigModel()
	case constant.RedisDB:
		flushConfigModel = flushManager.GetRedisFlushConfigModel()
	case constant.Other:
		flushConfigModel = flushManager.GetOtherFlushConfigModel()
	default:
		logger.Printf("flushConfig model is nil ")
		return nil
	}
	return NewCommConfigFlush(flushConfigModel)
}
